import {
  AppStoreServerAPIClient,
  Environment,
  // GetTransactionHistoryVersion,
  // HistoryResponse,
  JWSTransactionDecodedPayload,
  NotificationTypeV2,
  // Order,
  // ProductType,
  ReceiptUtility,
  ResponseBodyV2DecodedPayload,
  SendTestNotificationResponse,
  SignedDataVerifier,
  // TransactionHistoryRequest,
} from '@apple/app-store-server-library';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import fs, { readFileSync } from 'fs';
import { AppPaymentOrderService } from './payment-order.service';
import { AppUserService } from '../user/user.service';
import { dateFormat } from 'src/utils/date.util';
import { PaymentOrder } from './payment-order.entity';
import { AppleRestoreSubscribeDto, AppleSubscribeDto } from './dto/add.dto';

const bundleId = 'com.shubai.aichat'; // 应用的bundle ID
const appleRootCAs: Buffer[] = loadRootCAs(); // 具体实现可能有所不同
const enableOnlineChecks = true;
const environment = Environment.SANDBOX;
const appAppleId = undefined; // 6453469526; // 应用的Apple ID, 当环境为生产环境时，appAppleId 是必需的
const verifier = new SignedDataVerifier(
  appleRootCAs,
  enableOnlineChecks,
  environment,
  bundleId,
  appAppleId,
);

const filePath = 'pay/ios-lib/SubscriptionKey_M3WTA5BAYV.p8'; // 私钥文件
// const teamId = 'F64U4AY34Z'; // 开发者账号的Team ID。
const issuerId = '7a045cdd-3ba9-49db-938a-d741bf23f6e0'; // 开发者账号的Team ID。
const keyId = 'M3WTA5bays'; // 私钥的key ID
const encodedKey = readFileSync(filePath, { encoding: 'utf8' }).toString(); // 私钥内容
/**
 * 内购服务端逻辑
 * 1. 接受ios端发过来的购买凭证
 * 2. 判断该凭证是否已经存在或者验证过, 并存储该凭证
 * 3. 将该凭证发送到苹果的服务器验证, 并将验证结果返回给客户端
 * 4. 如果需要, 修改用户的会员权限
 * 5. 考虑网络异常情况, 服务器的验证是一个可恢复的队列, 如果网络失败则重试
 */

@Injectable()
export class IosAppPayService {
  private access_token: string;
  private expires_in: number;
  private timestamp: number;

  constructor(
    private configService: ConfigService,
    private readonly appPaymentOrderService: AppPaymentOrderService,
    private readonly appUserService: AppUserService,
  ) {}

  /**
   * 支付回调
   * @param payload
   * @returns
   */
  paySystemPush(notificationPayload: string) {
    // const notificationPayload = 'ey...';

    return new Promise((resolve, reject) => {
      verifier
        .verifyAndDecodeNotification(notificationPayload)
        .then((decodedPayload: ResponseBodyV2DecodedPayload) => {
          console.log('decodedPayload', decodedPayload);
          switch (decodedPayload.notificationType) {
            case NotificationTypeV2.TEST: {
              console.log('test通知类型');
              break;
            }
            case NotificationTypeV2.CONSUMPTION_REQUEST: {
              console.log('退款中通知类型');
              // 退款中
              break;
            }
            case NotificationTypeV2.REFUND: {
              // 退款成功
              this.updateOrder(decodedPayload).then(
                ({ order, decodedPayload }) => {
                  this.appPaymentOrderService.update({
                    ...order,
                    payStatus: 4, // 4:已退款
                    // orderCode: decodedPayload.appAccountToken,
                  });
                  this.appUserService.updateVipById(
                    order.userId,
                    0,
                    dateFormat(
                      decodedPayload.expiresDate
                        ? new Date(decodedPayload.expiresDate)
                        : new Date(),
                    ),
                    decodedPayload.productId,
                  );
                  resolve(true);
                },
              );
              break;
            }
            case NotificationTypeV2.REFUND_REVERSED: {
              // 撤销退款
              this.updateOrder(decodedPayload).then(
                ({ order, decodedPayload }) => {
                  this.appPaymentOrderService.update({
                    ...order,
                    payStatus: 1, // 1:已付款
                    // orderCode: decodedPayload.appAccountToken,
                  });
                  this.appUserService.updateVipById(
                    order.userId,
                    1,
                    dateFormat(
                      decodedPayload.expiresDate
                        ? new Date(decodedPayload.expiresDate)
                        : new Date(),
                    ),
                    decodedPayload.productId,
                  );
                  resolve(true);
                },
              );
              break;
            }

            case NotificationTypeV2.DID_RENEW: // 客户的订阅已成功自动续订了新的交易期
            case NotificationTypeV2.SUBSCRIBED: {
              // 已订阅，表示用户购买成功，已付款
              this.updateOrder(decodedPayload).then(
                ({ order, decodedPayload }) => {
                  this.appPaymentOrderService.update({
                    ...order,
                    payStatus: 1, // 1:已支付
                    // orderCode: decodedPayload.appAccountToken,
                  });
                  this.appUserService.updateVipById(
                    order.userId,
                    1,
                    dateFormat(
                      decodedPayload.expiresDate
                        ? new Date(decodedPayload.expiresDate)
                        : new Date(),
                    ),
                    decodedPayload.productId,
                  );
                  resolve(true);
                },
              );
              break;
            }

            default: {
              console.log('未知的通知类型', decodedPayload);
            }
          }
          resolve(true);
        })
        .catch((err) => {
          reject(err);
        });
    });
  }

  async updateOrder(decodedPayload: ResponseBodyV2DecodedPayload): Promise<{
    order: PaymentOrder;
    decodedPayload: JWSTransactionDecodedPayload;
  }> {
    return new Promise((resolve, reject) => {
      this.verifyAndDecodeTransaction(decodedPayload.data.signedTransactionInfo)
        .then(async (res) => {
          console.log('JWSTransactionDecodedPayload', res);

          const appPaymentOrder =
            await this.appPaymentOrderService.findOneByTransactionId(
              res.originalTransactionId,
            );

          if (appPaymentOrder) {
            console.log('updateOrder appPaymentOrder', appPaymentOrder);
            resolve({ order: appPaymentOrder, decodedPayload: res });
          } else {
            console.log('未找到订单');
            reject();
          }
        })
        .catch((err) => {
          console.log('verifyAndDecodeTransaction err', err);
          reject(err);
        });
    });
  }

  async subscribe(
    uid: string,
    data: AppleSubscribeDto,
  ): Promise<JWSTransactionDecodedPayload> {
    const { appReceipt } = data;
    const userId = uid;
    console.log('subscribe', data);
    const client = new AppStoreServerAPIClient(
      encodedKey,
      keyId,
      issuerId,
      bundleId,
      environment,
    );
    return new Promise((resolve, reject) => {
      // 创建ReceiptUtility实例，用于处理收据
      const receiptUtil = new ReceiptUtility();
      // 从应用收据中提取事务ID
      const transactionId =
        receiptUtil.extractTransactionIdFromAppReceipt(appReceipt);
      // 如果成功提取到事务ID，则继续查询事务历史
      if (transactionId != null) {
        // 定义事务历史请求参数
        // const transactionHistoryRequest: TransactionHistoryRequest = {
        //   sort: Order.ASCENDING, // 按升序排序
        //   revoked: false, // 不包括已撤销的事务
        //   productTypes: [ProductType.AUTO_RENEWABLE], // 只包括自动续订产品类型
        // };
        // const response: HistoryResponse | null = null; // 用于存储响应数据
        // const transactions: string[] = []; // 用于存储事务签名字符串的数组

        client
          .getTransactionInfo(transactionId)
          .then((transactionInfo) => {
            // 获取交易信息
            console.log('获取交易信息 transactionInfo', transactionInfo);
            this.verifyAndDecodeTransaction(
              transactionInfo.signedTransactionInfo,
            )
              .then(async (decodedPayload) => {
                console.log('JWSTransactionDecodedPayload', decodedPayload);
                this.appPaymentOrderService.add({
                  // this.appPaymentOrderService.updateByCode({
                  userId,
                  payStatus: 1,
                  transactionId: decodedPayload.originalTransactionId,
                  // appReceipt,
                  // orderCode: data.orderCode,
                });
                this.appUserService.updateVipById(
                  userId,
                  1,
                  dateFormat(
                    decodedPayload.expiresDate
                      ? new Date(decodedPayload.expiresDate)
                      : new Date(),
                  ),
                  decodedPayload.productId,
                );
                resolve(decodedPayload);
              })
              .catch((err) => {
                reject(err);
              });
          })
          .catch((err) => {
            console.log('getTransactionInfo err', err);
            reject(err);
          });
      } else {
        reject();
      }
    });
    // })

    // // 循环查询事务历史，直到没有更多数据
    // do {
    //   const revisionToken =
    //     response !== null && response.revision !== null
    //       ? response.revision
    //       : null; // 获取修订令牌（如果有）

    // 调用客户端的getTransactionHistory方法查询事务历史
    //   response = await client.getTransactionHistory(
    //     transactionId,
    //     revisionToken,
    //     transactionHistoryRequest,
    //     GetTransactionHistoryVersion.V2,
    //   );

    //   // 如果响应中包含已签名的事务，则将其添加到事务数组中
    //   if (response.signedTransactions) {
    //     transactions = transactions.concat(response.signedTransactions);
    //   }
    // } while (response.hasMore); // 如果还有更多数据，则继续查询

    // 打印所有事务签名字符串
    // console.log(transactions);
    // }
  }

  async restoreSubscription(
    userId: string,
    data: AppleRestoreSubscribeDto,
  ): Promise<JWSTransactionDecodedPayload> {
    return new Promise((resolve, reject) => {
      const { transactionId } = data;
      console.log('subscribe', data);
      const client = new AppStoreServerAPIClient(
        encodedKey,
        keyId,
        issuerId,
        bundleId,
        environment,
      );
      client
        .getTransactionInfo(transactionId)
        .then((transactionInfo) => {
          // 获取交易信息
          console.log('获取交易信息 transactionInfo', transactionInfo);
          this.verifyAndDecodeTransaction(transactionInfo.signedTransactionInfo)
            .then(async (decodedPayload) => {
              console.log('JWSTransactionDecodedPayload', decodedPayload);
              this.appPaymentOrderService.add({
                // this.appPaymentOrderService.updateByCode({
                userId,
                payStatus: 1,
                transactionId: decodedPayload.originalTransactionId,
                // appReceipt: '',
                // orderCode: data.orderCode,
              });
              this.appUserService.updateVipById(
                userId,
                1,
                dateFormat(
                  decodedPayload.expiresDate
                    ? new Date(decodedPayload.expiresDate)
                    : new Date(),
                ),
                decodedPayload.productId,
              );
              resolve(decodedPayload);
            })
            .catch((err) => {
              reject(err);
            });
        })
        .catch((err) => {
          console.log('getTransactionInfo err', err);
          reject(err);
        });
    });
  }

  /**
   * 要求App Store服务器通知向您的服务器发送测试通知。
   */
  async test() {
    const client = new AppStoreServerAPIClient(
      encodedKey,
      keyId,
      issuerId,
      bundleId,
      environment,
    );

    try {
      const response: SendTestNotificationResponse =
        await client.requestTestNotification();
      client
        .getTestNotificationStatus(response.testNotificationToken)
        .then((res) => {
          console.log('getTestNotificationStatus', res);
        })
        .catch((err) => {
          console.error('getTestNotificationStatus', err);
        });
    } catch (e) {
      console.error(e);
    }
  }

  /**
   * 验证并解码交易
   * @param signedTransactionInfo
   * @returns
   */
  async verifyAndDecodeTransaction(
    signedTransactionInfo: string,
  ): Promise<JWSTransactionDecodedPayload> {
    return new Promise((resolve, reject) => {
      verifier
        .verifyAndDecodeTransaction(signedTransactionInfo)
        .then((data: JWSTransactionDecodedPayload) => {
          const {
            price,
            productId,
            quantity,
            currency,
            purchaseDate,
            appAccountToken,
          } = data;

          const uuid = appAccountToken;
          console.log(
            '回调通知',
            price,
            productId,
            quantity,
            currency,
            purchaseDate,
            uuid,
          );
          resolve(data);
        })
        .catch((error) => {
          console.error('verifyAndDecodeTransaction失败', error);
          reject(error);
        });
    });
  }
}

// 读取 PEM 格式的 CA 证书
function loadRootCAs() {
  return [Buffer.from(fs.readFileSync('pay/ios-lib/AppleRootCA-G3.pem'))];
}
